import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import os from 'os';
import mongoose from 'mongoose';
import { ApiResponseBuilder, ErrorCode } from '../types/index.js';

/**
 * 健康检查路由
 */
export async function healthRoutes(fastify: FastifyInstance) {
  // 简单健康检查
  fastify.get('/health', async (_request: FastifyRequest, reply: FastifyReply) => {
    const response = ApiResponseBuilder.success({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      uptime: process.uptime()
    });

    return reply.send(response);
  });

  // 详细健康检查
  fastify.get('/health/detailed', async (_request: FastifyRequest, reply: FastifyReply) => {


    // 检查各个服务状态
    const services = await checkServices();

    // 获取内存使用情况

    const totalMem = os.totalmem();
    const freeMem = os.freemem();
    const usedMem = totalMem - freeMem;

    // 确定整体健康状态
    const overallStatus = determineOverallStatus(services);

    const healthCheck = {
      status: overallStatus,
      timestamp: new Date().toISOString(),
      version: process.env['npm_package_version'] || '1.0.0',
      services,
      uptime: process.uptime(),
      memory: {
        used: Math.round(usedMem / 1024 / 1024), // MB
        total: Math.round(totalMem / 1024 / 1024), // MB
        percentage: Math.round((usedMem / totalMem) * 100)
      },
      system: {
        platform: os.platform(),
        nodeVersion: process.version,
        pid: process.pid
      }
    };

    const response = ApiResponseBuilder.success(healthCheck);
    const statusCode = overallStatus === 'healthy' ? 200 : overallStatus === 'degraded' ? 200 : 503;

    return reply.status(statusCode).send(response);
  });

  // 就绪检查 (用于 Kubernetes readiness probe)
  fastify.get('/ready', async (_request: FastifyRequest, reply: FastifyReply) => {
    try {
      // 检查关键服务
      const mongoStatus = await checkMongoDB();

      if (mongoStatus.status === 'down') {
        return reply.status(503).send(
          ApiResponseBuilder.error(
            ErrorCode.EXTERNAL_SERVICE_ERROR,
            '服务尚未就绪',
            { reason: 'Database connection failed' }
          )
        );
      }

      return reply.send(
        ApiResponseBuilder.success({
          status: 'ready',
          timestamp: new Date().toISOString()
        })
      );
    } catch (error) {
      return reply.status(503).send(
        ApiResponseBuilder.error(
          ErrorCode.EXTERNAL_SERVICE_ERROR,
          '服务尚未就绪',
          { error: (error as Error).message }
        )
      );
    }
  });

  // 存活检查 (用于 Kubernetes liveness probe)
  fastify.get('/alive', async (_request: FastifyRequest, reply: FastifyReply) => {
    return reply.send(
      ApiResponseBuilder.success({
        status: 'alive',
        timestamp: new Date().toISOString(),
        pid: process.pid,
        uptime: process.uptime()
      })
    );
  });
}

/**
 * 检查各个服务状态
 */
async function checkServices() {
  const services: Record<string, any> = {};

  // 检查 MongoDB
  // 检查 MongoDB
  services['mongodb'] = await checkMongoDB();

  // 检查 Redis (如果配置了)
  // services.redis = await checkRedis();

  // 检查 RabbitMQ (如果配置了)
  // services.rabbitmq = await checkRabbitMQ();

  return services;
}

/**
 * 检查 MongoDB 连接状态
 */
async function checkMongoDB() {
  try {
    const startTime = Date.now();
    const state = mongoose.connection.readyState;
    const responseTime = Date.now() - startTime;

    switch (state) {
      case 0:
        return { status: 'down', error: 'Disconnected', responseTime };
      case 1:
        // 执行简单查询测试连接
        await mongoose.connection.db?.admin().ping();
        return { status: 'up', responseTime };
      case 2:
        return { status: 'degraded', error: 'Connecting', responseTime };
      case 3:
        return { status: 'degraded', error: 'Disconnecting', responseTime };
      default:
        return { status: 'down', error: 'Unknown state', responseTime };
    }
  } catch (error) {
    return {
      status: 'down',
      error: (error as Error).message,
      responseTime: 0
    };
  }
}

/**
 * 确定整体健康状态
 */
function determineOverallStatus(services: Record<string, any>): 'healthy' | 'degraded' | 'unhealthy' {
  const serviceStatuses = Object.values(services).map(service => service.status);

  if (serviceStatuses.every(status => status === 'up')) {
    return 'healthy';
  }

  if (serviceStatuses.some(status => status === 'down')) {
    return 'unhealthy';
  }

  return 'degraded';
}
